home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / src / gas-211 / gas / atof-gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  16.6 KB  |  574 lines

  1. /* atof_generic.c - turn a string of digits into a Flonum
  2.    Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GAS, the GNU Assembler.
  5.  
  6.    GAS is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    GAS is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with GAS; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <ctype.h>
  21. #include <string.h>
  22.  
  23. #include "as.h"
  24.  
  25. #ifdef __GNUC__
  26. #define alloca __builtin_alloca
  27. #else
  28. #ifdef sparc
  29. #include <alloca.h>
  30. #endif
  31. #endif
  32.  
  33. #ifndef FALSE
  34. #define FALSE (0)
  35. #endif
  36. #ifndef TRUE
  37. #define TRUE  (1)
  38. #endif
  39.  
  40. /***********************************************************************\
  41.  *                                    *
  42.  *    Given a string of decimal digits , with optional decimal    *
  43.  *    mark and optional decimal exponent (place value) of the        *
  44.  *    lowest_order decimal digit: produce a floating point        *
  45.  *    number. The number is 'generic' floating point: our        *
  46.  *    caller will encode it for a specific machine architecture.    *
  47.  *                                    *
  48.  *    Assumptions                            *
  49.  *        uses base (radix) 2                    *
  50.  *        this machine uses 2's complement binary integers    *
  51.  *        target flonums use "      "         "       "        *
  52.  *        target flonums exponents fit in a long        *
  53.  *                                    *
  54.  \***********************************************************************/
  55.  
  56. /*
  57.  
  58.   Syntax:
  59.  
  60.   <flonum> ::= <optional-sign> <decimal-number> <optional-exponent>
  61.   <optional-sign> ::= '+' | '-' | {empty}
  62.   <decimal-number> ::= <integer>
  63.   | <integer> <radix-character>
  64.   | <integer> <radix-character> <integer>
  65.   | <radix-character> <integer>
  66.  
  67.   <optional-exponent> ::= {empty}
  68.   | <exponent-character> <optional-sign> <integer>
  69.  
  70.   <integer> ::= <digit> | <digit> <integer>
  71.   <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
  72.   <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
  73.   <radix-character> ::= {one character from "string_of_decimal_marks"}
  74.  
  75.   */
  76.  
  77. int                /* 0 if OK */
  78. atof_generic (
  79.            address_of_string_pointer,    /* return pointer to just
  80.                         AFTER number we read. */
  81.            string_of_decimal_marks,    /* At most one per number. */
  82.            string_of_decimal_exponent_marks,
  83.            address_of_generic_floating_point_number)
  84.      char **address_of_string_pointer;
  85.      const char *string_of_decimal_marks;
  86.      const char *string_of_decimal_exponent_marks;
  87.      FLONUM_TYPE *address_of_generic_floating_point_number;
  88. {
  89.   int return_value;        /* 0 means OK. */
  90.   char *first_digit;
  91.   /* char *last_digit; JF unused */
  92.   int number_of_digits_before_decimal;
  93.   int number_of_digits_after_decimal;
  94.   long decimal_exponent;
  95.   int number_of_digits_available;
  96.   char digits_sign_char;
  97.  
  98.   /*
  99.      * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
  100.      * It would be simpler to modify the string, but we don't; just to be nice
  101.      * to caller.
  102.      * We need to know how many digits we have, so we can allocate space for
  103.      * the digits' value.
  104.      */
  105.  
  106.   char *p;
  107.   char c;
  108.   int seen_significant_digit;
  109.  
  110.   first_digit = *address_of_string_pointer;
  111.   c = *first_digit;
  112.  
  113.   if (c == '-' || c == '+')
  114.     {
  115.       digits_sign_char = c;
  116.       first_digit++;
  117.     }
  118.   else
  119.     digits_sign_char = '+';
  120.  
  121.   if ((first_digit[0] == 'n' || first_digit[0] == 'N')
  122.       && (first_digit[1] == 'a' || first_digit[1] == 'A')
  123.       && (first_digit[2] == 'n' || first_digit[2] == 'N'))
  124.     {
  125.       address_of_generic_floating_point_number->sign = 0;
  126.       address_of_generic_floating_point_number->exponent = 0;
  127.       address_of_generic_floating_point_number->leader =
  128.     address_of_generic_floating_point_number->low;
  129.       *address_of_string_pointer = first_digit + 3;
  130.       return (0);
  131.     }
  132.  
  133.   if ((first_digit[0] == 'i' || first_digit[0] == 'I')
  134.       && (first_digit[1] == 'n' || first_digit[1] == 'N')
  135.       && (first_digit[2] == 'f' || first_digit[2] == 'F'))
  136.     {
  137.       address_of_generic_floating_point_number->sign =
  138.     digits_sign_char == '+' ? 'P' : 'N';
  139.       address_of_generic_floating_point_number->exponent = 0;
  140.       address_of_generic_floating_point_number->leader =
  141.     address_of_generic_floating_point_number->low;
  142.  
  143.       if ((first_digit[3] == 'i'
  144.        || first_digit[3] == 'I')
  145.       && (first_digit[4] == 'n'
  146.           || first_digit[4] == 'N')
  147.       && (first_digit[5] == 'i'
  148.           || first_digit[5] == 'I')
  149.       && (first_digit[6] == 't'
  150.           || first_digit[6] == 'T')
  151.       && (first_digit[7] == 'y'
  152.           || first_digit[7] == 'Y'))
  153.     {
  154.       *address_of_string_pointer = first_digit + 8;
  155.     }
  156.       else
  157.     {
  158.       *address_of_string_pointer = first_digit + 3;
  159.     }
  160.       return (0);
  161.     }
  162.  
  163.   number_of_digits_before_decimal = 0;
  164.   number_of_digits_after_decimal = 0;
  165.   decimal_exponent = 0;
  166.   seen_significant_digit = 0;
  167.   for (p = first_digit; (((c = *p) != '\0')
  168.              && (!c || !strchr (string_of_decimal_marks, c))
  169.           && (!c || !strchr (string_of_decimal_exponent_marks, c)));
  170.        p++)
  171.     {
  172.       if (isdigit (c))
  173.     {
  174.       if (seen_significant_digit || c > '0')
  175.         {
  176.           ++number_of_digits_before_decimal;
  177.           seen_significant_digit = 1;
  178.         }
  179.       else
  180.         {
  181.           first_digit++;
  182.         }
  183.     }
  184.       else
  185.     {
  186.       break;        /* p -> char after pre-decimal digits. */
  187.     }
  188.     }                /* For each digit before decimal mark. */
  189.  
  190. #ifndef OLD_FLOAT_READS
  191.   /* Ignore trailing 0's after the decimal point.  The original code here
  192.      * (ifdef'd out) does not do this, and numbers like
  193.      *    4.29496729600000000000e+09    (2**31)
  194.      * come out inexact for some reason related to length of the digit
  195.      * string.
  196.      */
  197.   if (c && strchr (string_of_decimal_marks, c))
  198.     {
  199.       int zeros = 0;        /* Length of current string of zeros */
  200.  
  201.       for (p++; (c = *p) && isdigit (c); p++)
  202.     {
  203.       if (c == '0')
  204.         {
  205.           zeros++;
  206.         }
  207.       else
  208.         {
  209.           number_of_digits_after_decimal += 1 + zeros;
  210.           zeros = 0;
  211.         }
  212.     }
  213.     }
  214. #else
  215.   if (c && strchr (string_of_decimal_marks, c))
  216.     {
  217.       for (p++; (((c = *p) != '\0')
  218.          && (!c || !strchr (string_of_decimal_exponent_marks, c)));
  219.        p++)
  220.     {
  221.       if (isdigit (c))
  222.         {
  223.           number_of_digits_after_decimal++;    /* This may be retracted below. */
  224.           if ( /* seen_significant_digit || */ c > '0')
  225.         {
  226.           seen_significant_digit = TRUE;
  227.         }
  228.         }
  229.       else
  230.         {
  231.           if (!seen_significant_digit)
  232.         {
  233.           number_of_digits_after_decimal = 0;
  234.         }
  235.           break;
  236.         }
  237.     }            /* For each digit after decimal mark. */
  238.     }
  239.  
  240.   while (number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal
  241.                    + number_of_digits_after_decimal] == '0')
  242.     --number_of_digits_after_decimal;
  243.   /* last_digit = p; JF unused */
  244. #endif
  245.  
  246.   if (c && strchr (string_of_decimal_exponent_marks, c))
  247.     {
  248.       char digits_exponent_sign_char;
  249.  
  250.       c = *++p;
  251.       if (c && strchr ("+-", c))
  252.     {
  253.       digits_exponent_sign_char = c;
  254.       c = *++p;
  255.     }
  256.       else
  257.     {
  258.       digits_exponent_sign_char = '+';
  259.     }
  260.  
  261.       for (; (c); c = *++p)
  262.     {
  263.       if (isdigit (c))
  264.         {
  265.           decimal_exponent = decimal_exponent * 10 + c - '0';
  266.           /*
  267.                  * BUG! If we overflow here, we lose!
  268.                  */
  269.         }
  270.       else
  271.         {
  272.           break;
  273.         }
  274.     }
  275.  
  276.       if (digits_exponent_sign_char == '-')
  277.     {
  278.       decimal_exponent = -decimal_exponent;
  279.     }
  280.     }
  281.  
  282.   *address_of_string_pointer = p;
  283.  
  284.  
  285.  
  286.   number_of_digits_available =
  287.     number_of_digits_before_decimal + number_of_digits_after_decimal;
  288.   return_value = 0;
  289.   if (number_of_digits_available == 0)
  290.     {
  291.       address_of_generic_floating_point_number->exponent = 0;    /* Not strictly necessary */
  292.       address_of_generic_floating_point_number->leader
  293.     = -1 + address_of_generic_floating_point_number->low;
  294.       address_of_generic_floating_point_number->sign = digits_sign_char;
  295.       /* We have just concocted (+/-)0.0E0 */
  296.  
  297.     }
  298.   else
  299.     {
  300.       int count;        /* Number of useful digits left to scan. */
  301.  
  302.       LITTLENUM_TYPE *digits_binary_low;
  303.       int precision;
  304.       int maximum_useful_digits;
  305.       int number_of_digits_to_use;
  306.       int more_than_enough_bits_for_digits;
  307.       int more_than_enough_littlenums_for_digits;
  308.       int size_of_digits_in_littlenums;
  309.       int size_of_digits_in_chars;
  310.       FLONUM_TYPE power_of_10_flonum;
  311.       FLONUM_TYPE digits_flonum;
  312.  
  313.       precision = (address_of_generic_floating_point_number->high
  314.            - address_of_generic_floating_point_number->low
  315.            + 1);    /* Number of destination littlenums. */
  316.  
  317.       /* Includes guard bits (two littlenums worth) */
  318.       maximum_useful_digits = (((double) (precision - 2))
  319.                    * ((double) (LITTLENUM_NUMBER_OF_BITS))
  320.                    / (LOG_TO_BASE_2_OF_10))
  321.     + 2;            /* 2 :: guard digits. */
  322.  
  323.       if (number_of_digits_available > maximum_useful_digits)
  324.     {
  325.       number_of_digits_to_use = maximum_useful_digits;
  326.     }
  327.       else
  328.     {
  329.       number_of_digits_to_use = number_of_digits_available;
  330.     }
  331.  
  332.       decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use;
  333.  
  334.       more_than_enough_bits_for_digits
  335.     = ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
  336.  
  337.       more_than_enough_littlenums_for_digits
  338.     = (more_than_enough_bits_for_digits
  339.        / LITTLENUM_NUMBER_OF_BITS)
  340.     + 2;
  341.  
  342.       /*
  343.          * Compute (digits) part. In "12.34E56" this is the "1234" part.
  344.          * Arithmetic is exact here. If no digits are supplied then
  345.          * this part is a 0 valued binary integer.
  346.          * Allocate room to build up the binary number as littlenums.
  347.          * We want this memory to disappear when we leave this function.
  348.          * Assume no alignment problems => (room for n objects) ==
  349.          * n * (room for 1 object).
  350.          */
  351.  
  352.       size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
  353.       size_of_digits_in_chars = size_of_digits_in_littlenums
  354.     * sizeof (LITTLENUM_TYPE);
  355.  
  356.       digits_binary_low = (LITTLENUM_TYPE *)
  357.     alloca (size_of_digits_in_chars);
  358.  
  359.       memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars);
  360.  
  361.       /* Digits_binary_low[] is allocated and zeroed. */
  362.  
  363.       /*
  364.          * Parse the decimal digits as if * digits_low was in the units position.
  365.          * Emit a binary number into digits_binary_low[].
  366.          *
  367.          * Use a large-precision version of:
  368.          * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
  369.          */
  370.  
  371.       for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)
  372.     {
  373.       c = *p;
  374.       if (isdigit (c))
  375.         {
  376.           /*
  377.                  * Multiply by 10. Assume can never overflow.
  378.                  * Add this digit to digits_binary_low[].
  379.                  */
  380.  
  381.           long carry;
  382.           LITTLENUM_TYPE *littlenum_pointer;
  383.           LITTLENUM_TYPE *littlenum_limit;
  384.  
  385.           littlenum_limit = digits_binary_low
  386.         + more_than_enough_littlenums_for_digits
  387.         - 1;
  388.  
  389.           carry = c - '0';    /* char -> binary */
  390.  
  391.           for (littlenum_pointer = digits_binary_low;
  392.            littlenum_pointer <= littlenum_limit;
  393.            littlenum_pointer++)
  394.         {
  395.           long work;
  396.  
  397.           work = carry + 10 * (long) (*littlenum_pointer);
  398.           *littlenum_pointer = work & LITTLENUM_MASK;
  399.           carry = work >> LITTLENUM_NUMBER_OF_BITS;
  400.         }
  401.  
  402.           if (carry != 0)
  403.         {
  404.           /*
  405.                      * We have a GROSS internal error.
  406.                      * This should never happen.
  407.                      */
  408.           as_fatal ("failed sanity check.");    /* RMS prefers abort() to any message. */
  409.         }
  410.         }
  411.       else
  412.         {
  413.           ++count;        /* '.' doesn't alter digits used count. */
  414.         }            /* if valid digit */
  415.     }            /* for each digit */
  416.  
  417.  
  418.       /*
  419.          * Digits_binary_low[] properly encodes the value of the digits.
  420.          * Forget about any high-order littlenums that are 0.
  421.          */
  422.       while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
  423.          && size_of_digits_in_littlenums >= 2)
  424.     size_of_digits_in_littlenums--;
  425.  
  426.       digits_flonum.low = digits_binary_low;
  427.       digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;
  428.       digits_flonum.leader = digits_flonum.high;
  429.       digits_flonum.exponent = 0;
  430.       /*
  431.          * The value of digits_flonum . sign should not be important.
  432.          * We have already decided the output's sign.
  433.          * We trust that the sign won't influence the other parts of the number!
  434.          * So we give it a value for these reasons:
  435.          * (1) courtesy to humans reading/debugging
  436.          *     these numbers so they don't get excited about strange values
  437.          * (2) in future there may be more meaning attached to sign,
  438.          *     and what was
  439.          *     harmless noise may become disruptive, ill-conditioned (or worse)
  440.          *     input.
  441.          */
  442.       digits_flonum.sign = '+';
  443.  
  444.       {
  445.     /*
  446.              * Compute the mantssa (& exponent) of the power of 10.
  447.              * If sucessful, then multiply the power of 10 by the digits
  448.              * giving return_binary_mantissa and return_binary_exponent.
  449.              */
  450.  
  451.     LITTLENUM_TYPE *power_binary_low;
  452.     int decimal_exponent_is_negative;
  453.     /* This refers to the "-56" in "12.34E-56". */
  454.     /* FALSE: decimal_exponent is positive (or 0) */
  455.     /* TRUE:  decimal_exponent is negative */
  456.     FLONUM_TYPE temporary_flonum;
  457.     LITTLENUM_TYPE *temporary_binary_low;
  458.     int size_of_power_in_littlenums;
  459.     int size_of_power_in_chars;
  460.  
  461.     size_of_power_in_littlenums = precision;
  462.     /* Precision has a built-in fudge factor so we get a few guard bits. */
  463.  
  464.     decimal_exponent_is_negative = decimal_exponent < 0;
  465.     if (decimal_exponent_is_negative)
  466.       {
  467.         decimal_exponent = -decimal_exponent;
  468.       }
  469.  
  470.     /* From now on: the decimal exponent is > 0. Its sign is seperate. */
  471.  
  472.     size_of_power_in_chars = size_of_power_in_littlenums
  473.       * sizeof (LITTLENUM_TYPE) + 2;
  474.  
  475.     power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
  476.     temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
  477.     memset ((char *) power_binary_low, '\0', size_of_power_in_chars);
  478.     *power_binary_low = 1;
  479.     power_of_10_flonum.exponent = 0;
  480.     power_of_10_flonum.low = power_binary_low;
  481.     power_of_10_flonum.leader = power_binary_low;
  482.     power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
  483.     power_of_10_flonum.sign = '+';
  484.     temporary_flonum.low = temporary_binary_low;
  485.     temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
  486.     /*
  487.              * (power) == 1.
  488.              * Space for temporary_flonum allocated.
  489.              */
  490.  
  491.     /*
  492.              * ...
  493.              *
  494.              * WHILE    more bits
  495.              * DO    find next bit (with place value)
  496.              *    multiply into power mantissa
  497.              * OD
  498.              */
  499.     {
  500.       int place_number_limit;
  501.       /* Any 10^(2^n) whose "n" exceeds this */
  502.       /* value will fall off the end of */
  503.       /* flonum_XXXX_powers_of_ten[]. */
  504.       int place_number;
  505.       const FLONUM_TYPE *multiplicand;    /* -> 10^(2^n) */
  506.  
  507.       place_number_limit = table_size_of_flonum_powers_of_ten;
  508.  
  509.       multiplicand = (decimal_exponent_is_negative
  510.               ? flonum_negative_powers_of_ten
  511.               : flonum_positive_powers_of_ten);
  512.  
  513.       for (place_number = 1;/* Place value of this bit of exponent. */
  514.            decimal_exponent;/* Quit when no more 1 bits in exponent. */
  515.            decimal_exponent >>= 1, place_number++)
  516.         {
  517.           if (decimal_exponent & 1)
  518.         {
  519.           if (place_number > place_number_limit)
  520.             {
  521.               /*
  522.                              * The decimal exponent has a magnitude so great that
  523.                              * our tables can't help us fragment it.  Although this
  524.                              * routine is in error because it can't imagine a
  525.                              * number that big, signal an error as if it is the
  526.                              * user's fault for presenting such a big number.
  527.                              */
  528.               return_value = ERROR_EXPONENT_OVERFLOW;
  529.               /*
  530.                              * quit out of loop gracefully
  531.                              */
  532.               decimal_exponent = 0;
  533.             }
  534.           else
  535.             {
  536. #ifdef TRACE
  537.               printf ("before multiply, place_number = %d., power_of_10_flonum:\n",
  538.                   place_number);
  539.  
  540.               flonum_print (&power_of_10_flonum);
  541.               (void) putchar ('\n');
  542. #endif
  543.               flonum_multip (multiplicand + place_number,
  544.                      &power_of_10_flonum, &temporary_flonum);
  545.               flonum_copy (&temporary_flonum, &power_of_10_flonum);
  546.             }        /* If this bit of decimal_exponent was computable.*/
  547.         }        /* If this bit of decimal_exponent was set. */
  548.         }            /* For each bit of binary representation of exponent */
  549. #ifdef TRACE
  550.       printf (" after computing power_of_10_flonum: ");
  551.       flonum_print (&power_of_10_flonum);
  552.       (void) putchar ('\n');
  553. #endif
  554.     }
  555.  
  556.       }
  557.  
  558.       /*
  559.          * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
  560.          * It may be the number 1, in which case we don't NEED to multiply.
  561.          *
  562.          * Multiply (decimal digits) by power_of_10_flonum.
  563.          */
  564.  
  565.       flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
  566.       /* Assert sign of the number we made is '+'. */
  567.       address_of_generic_floating_point_number->sign = digits_sign_char;
  568.  
  569.     }                /* If we had any significant digits. */
  570.   return (return_value);
  571. }                /* atof_generic () */
  572.  
  573. /* end of atof_generic.c */
  574.